package com.itheima.mongodb.mapper;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.commons.pojo.UserLocation;
import com.itheima.commons.vo.UserLocationVo;
import com.itheima.interfaces.BaiDuApi;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class BaiDuMapperImpl implements BaiDuApi {
    @Autowired
    private ElasticsearchTemplate esTemplate;

    @PostConstruct
    public void init() {
        if (!esTemplate.indexExists(UserLocation.class)) {
            boolean index = esTemplate.createIndex(UserLocation.class);
            if (index) {
                esTemplate.putMapping(UserLocation.class);
            }
        }
    }

    /**
     * 往elasticsearch中添加自己的地理位置
     *
     * @param
     */
    @Override
    public Boolean saveLocation(Double latitude, Double longitude, String addrStr, Long UserId) {
        //查询userId 判断是否上传过位置
        UserLocationVo userLocationVo = selectByUserId(UserId);
        //上传过 修改位置
        if (ObjectUtil.isNotEmpty(userLocationVo)) {
            UpdateQuery query = new UpdateQuery();
            query.setClazz(UserLocation.class);
            query.setId(UserId.toString());
            UpdateRequest updateRequest = new UpdateRequest();
            Map map = new HashMap();
            map.put("location", new GeoPoint().reset(latitude, longitude));
            map.put("address", addrStr);
            updateRequest.doc(map);
            query.setUpdateRequest(updateRequest);
            UpdateResponse update = esTemplate.update(query);
            return update.getResult().getOp() >= 1;
        }
        //没上传过  上传位置
        UserLocation userLocation = new UserLocation();
        userLocation.setUserId(UserId);
        userLocation.setLocation(new GeoPoint().reset(latitude, longitude));
        userLocation.setAddress(addrStr);
        userLocation.setCreated(System.currentTimeMillis());
        userLocation.setUpdated(System.currentTimeMillis());
        userLocation.setLastUpdated(System.currentTimeMillis());


        IndexQuery query = new IndexQuery();
        query.setObject(userLocation);
        String index = esTemplate.index(query);
        return StrUtil.isNotBlank(index);
    }

    @Override
    public UserLocationVo selectByUserId(Long userId) {

        GetQuery query = new GetQuery();
        query.setId(Convert.toStr(userId));
        UserLocation userLocation = esTemplate.queryForObject(query, UserLocation.class);
        return UserLocationVo.format(userLocation);
    }

    @Override
    public List<UserLocationVo> selectSearch(Double latitude, Double longitude, Integer counts, Double distance) {
        List<UserLocation> userLocations = esTemplate.queryForList(new NativeSearchQueryBuilder()
                        .withQuery(QueryBuilders.geoDistanceQuery("location").point(latitude, longitude).distance(distance / 1000, DistanceUnit.KILOMETERS))
                        .withSort(SortBuilders.geoDistanceSort("location", new GeoPoint(latitude, longitude)))
                        .withPageable(PageRequest.of(0, counts))

                        .build()
                , UserLocation.class);
        return  UserLocationVo.formatToList(userLocations);
    }
}
